#include "xlcomm/net/rpc/rpc_server.h"

#include "xlcomm/base/logger.h"

namespace xlcomm {
namespace net {

RpcServer::RpcServer(EventLoop* loop, const InetAddress& listen_addr)
    : server_(loop, listen_addr, "RpcServer") {
  codec_.set_rpc_cb(std::bind(&RpcServer::OnRpcCall, this, _1, _2));
  server_.set_message_callback(
      std::bind(&RpcCodec::OnMessage, codec_, _1, _2, _3));
}

void RpcServer::OnRpcCall(const TcpConnectionPtr& conn, RpcMeta& meta) {
  LOG_TRACE << "----";
  LOG_INFO << "receive rpc call, id:" << meta.id << " service:" << meta.service
           << " method:" << meta.method;
  do {
    if (meta.type != RPC_TYPE_REQUEST) {
      meta.errcode = RPC_ERR_WRONG_PROTO;
      LOG_WARN << "It's not RPC_TYPE_REQUEST";
      break;
    }

    auto it = reg_methods_.find(meta.service + "::" + meta.method);
    if (it == reg_methods_.end()) {
      meta.errcode = RPC_ERR_NO_METHOD;
      LOG_WARN << "Can not found register rpc method";
      break;
    }

    const RpcMethod& method = it->second;
    RpcParamReader reqReader(meta.request);
    RpcParam resParam;
    method(reqReader, resParam);
    meta.response = resParam.getMsg();
    meta.errcode = RPC_ERR_OK;
  } while (0);

  meta.type = RPC_TYPE_RESPONSE;
  codec_.Send(conn, meta);
}

}  // namespace net
}  // namespace xlcomm